<template>
  <div class="xftp_container">
    <el-card>
      <el-form :model="ftpData.formData" ref="ftpRef" label-position="left" label-width="auto"
        :rules="ftpData.formRules" inline>
        <el-form-item v-for="(item, key) in ftpData.formItems" :label="item.label" :prop="item.prop">
          <el-input style="width: 100%;" v-model="ftpData.formData[key]" :show-password="key === 'password'" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="connectFtp">连接</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <el-card class="h-600px">
      <div class="fileSystem_container flex  gap-20px">
        <div class="w-50% flex-1">
          <div class="flex items-center m-b-20px">
            <img class="w-20px cursor-pointer m-r-10px h-15px" :src="FileIcon" />
            <span>本地目录:{{ localFileData.pwd }}</span>
          </div>
          <div>
            <el-button color="#1c2945" v-show="localFileData.pwd !== '/' && localFileData.pwd !== ''"
              @click="backLocalParentDirectory" class="m-b-10px">返回上级目录</el-button>
          </div>
          <div class="file-list-container" @dragover="handleDragOver" @dragenter.prevent @dragleave="handleDragLeave"
            @drop="handleDrop" :class="{ 'drag-over': isDragOver }">
            <div v-for="item in localFileData.list" :key="item.name" class="m-b-10px file_item h-20px flex items-center"
              @click="getLocalChildFile(item)" draggable="true" @dragstart="handleLocalDragStart($event, item)"
              @dragend="handleLocalDragEnd">
              <svg-icon :icon-class="item.icon" class="text-lg m-r-5px"></svg-icon>
              <span>{{ item.name }}</span>
            </div>
          </div>
        </div>
        <div class="w-50% flex-1 h-80%">
          <div class="flex  items-center m-b-20px">
            <img class="w-20px cursor-pointer m-r-10px  h-15px" :src="FileIcon" />
            <span>目标机目录:{{ targetFileData.pwd }}</span>
          </div>
          <div>
            <el-button color="#1c2945" v-show="targetFileData.pwd !== '/' && targetFileData.pwd !== ''"
              @click="backParentDirectory" class="m-b-10px">返回上级目录</el-button>
          </div>
          <div class="file-list-container" @dragover="handleDragOver" @dragenter.prevent @dragleave="handleDragLeave"
            @drop="handleTargetDrop" :class="{ 'drag-over': isDragOver }">
            <div v-for="item in targetFileData.list" :key="item.name"
              class="m-b-10px file_item h-20px flex items-center" @contextmenu.prevent="handleContextMenu($event, item)"
              @click="getChildFile(item)" draggable="true" @dragstart="handleDragStart($event, item)"
              @dragend="handleDragEnd">
              <svg-icon :icon-class="item.icon" class="text-lg"></svg-icon>
              <span>{{ item.name }}</span>
            </div>
          </div>
        </div>
        <transition name="fade">
          <div v-show="targetFileData.showContextMenu" class="context-menu"
            :style="{ left: targetFileData.contextMenuX + 'px', top: targetFileData.contextMenuY + 'px' }">
            <ul class="menu-list">
              <template v-for="item in targetFileData.menuList" :key="item.name">
                <li v-if="(item.name === '打开' && targetFileData?.selectedFile?.isDirectory) || (item.name !== '打开')"
                  @click="item.click(item)">
                  {{ item.name }}
                </li>
              </template>
            </ul>
          </div>
        </transition>
      </div>
    </el-card>
    <el-dialog v-model="downloadProgress.visible" title="下载进度" width="30%" :close-on-click-modal="false">
      <el-progress :percentage="downloadProgress.percent" :text-inside="true" :stroke-width="24" status="success" />
    </el-dialog>
    <el-dialog v-model="uploadProgress.visible" title="上传进度" width="30%" :close-on-click-modal="false">
      <el-progress :percentage="uploadProgress.percent" :text-inside="true" :stroke-width="24" status="success" />
    </el-dialog>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { ElNotificationFn } from '@/utils/computedUtils'
import FileIcon from '@/assets/imgs/file.png'
export default defineComponent({
  name: 'Xftp',
})
</script>
<script setup lang="ts">
const ftpRef = ref<any>()
const ftpData: any = ref({
  formData: {
    host: '192.168.2.75',
    port: 21,
    user: 'anonymous',
    password: 'anonymous'
  },

  formRules: {
    host: [{ required: true, message: '请输入主机地址', trigger: 'blur' }],
    port: [{ required: true, message: '请输入端口号', trigger: 'blur' }],
    user: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
    password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
  },

  formItems: {
    host: {
      label: '主机地址',
      prop: 'host',
    },
    port: {
      label: '端口号',
      prop: 'port',
    },
    user: {
      label: '用户名',
      prop: 'user',
    },
    password: {
      label: '密码',
      prop: 'password',
    }
  }
})
async function connectFtp() {
  try {
    await ftpRef.value.validate()
    window.electron.sendMessageToMain({
      commands: 'JRLC.FTP.CONNECT',
      data: {
        host: ftpData.value.formData.host,
        port: ftpData.value.formData.port,
        user: ftpData.value.formData.user,
        password: ftpData.value.formData.password
      }
    })
  } catch (error) {
    console.log(error)
  }
}
const iconList: string[] = [
  'tree_item_c',
  'tree_item_cpp',
  'tree_item_d',
  'tree_item_default',
  'tree_item_folder',
  'tree_item_h',
  'tree_item_json',
  'tree_item_log',
  'tree_item_markdown',
  'tree_item_mk',
  'tree_item_o',
  'tree_item_python',
  'tree_item_setting',
  'tree_item_sh',
  'tree_item_ts',
  'tree_item_txt',
  'tree_item_yml',
  'tree_item_zip',
]
const targetFileData: any = ref({
  list: [],
  pwd: '',
  showContextMenu: false,
  contextMenuX: 0,
  contextMenuY: 0,
  selectedFile: null,
  menuList: [
    {
      name: '下载',
      click: () => window.electron.sendMessageToMain({ commands: 'JRLC.FTP.DOWNLOAD', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port, path: targetFileData.value.selectedFile.name } })
    },
    {
      name: '删除',
      click: () => window.electron.sendMessageToMain({ commands: 'JRLC.FTP.REMOVE', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port, path: targetFileData.value.selectedFile.name } })
    },
    {
      name: '打开',
      click: () => window.electron.sendMessageToMain({ commands: 'JRLC.FTP.LIST', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port, path: targetFileData.value.selectedFile.name } })
    }
  ]
})
function getFileIcon(fileName: string): string {
  const extension = fileName.split('.')[fileName.split('.').length - 1]
  return iconList.find((iconItem: string) => extension && iconItem.split('_')[2]?.includes(extension)) || 'tree_item_default'
}
function setFileList(data: any) {
  targetFileData.value.list = []
  targetFileData.value.pwd = data.pwd
  data.list.map((item: any) => {
    const icon = item.isDirectory ? 'tree_item_folder' : getFileIcon(item.name)
    targetFileData.value.list.push({
      name: item.name,
      isFile: item.isFile,
      isDirectory: item.isDirectory,
      icon
    })
  })
}
function handleContextMenu(event: any, item: any) {
  event.preventDefault()
  targetFileData.value.selectedFile = item
  targetFileData.value.contextMenuX = event.clientX
  nextTick(() => {
    const menuElement = document.querySelector('.context-menu')
    if (menuElement) {
      const menuHeight = menuElement.offsetHeight
      targetFileData.value.contextMenuY = event.clientY - menuHeight
    }
  })
  targetFileData.value.showContextMenu = true
  setTimeout(() => {
    window.addEventListener('click', closeContextMenu)
  }, 0)
}
function closeContextMenu() {
  targetFileData.value.showContextMenu = false
  window.removeEventListener('click', closeContextMenu)
}
function getChildFile(item: any) {
  if (item.isDirectory) {
    window.electron.sendMessageToMain({ commands: 'JRLC.FTP.LIST', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port, path: item.name } })
  }
}
function backParentDirectory() {
  window.electron.sendMessageToMain({ commands: 'JRLC.FTP.CDUP', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port } })
}
const localFileData: any = ref({
  list: [],
  pwd: '/',
})
function getLocalDrives() {
  window.electron.sendMessageToMain({ commands: 'JRLC.LOCAL.DRIVES' })
}
function setLocalDrives(data: any) {
  localFileData.value.pwd = data.path
  localFileData.value.list = data.list.map((item: any) => {
    const icon = item.isDirectory ? 'tree_item_folder' : getFileIcon(item.name)
    return {
      ...item,
      icon: icon
    }
  })
}
function getLocalChildFile(item: any) {
  if (!item.isDirectory) return
  const dirPath = item.type === 'drive' ? item.name : item.fullPath;
  window.electron.sendMessageToMain({ commands: 'JRLC.LOCAL.LIST', data: { dirPath } });
}
function setLocalFileList(data: any) {
  localFileData.value.pwd = data.path
  localFileData.value.list = data.files.map((item: any) => {
    const icon = item.isDirectory ? 'tree_item_folder' : getFileIcon(item.name)
    return {
      ...item,
      icon
    }
  })
}
function backLocalParentDirectory() {
  const currentPath = localFileData.value.pwd;
  // 检查是否是Windows系统的根目录格式（如 C:\）
  if (/^[A-Za-z]:\\$/.test(currentPath)) {
    // 如果是根目录，则获取驱动器列表
    window.electron.sendMessageToMain({ commands: 'JRLC.LOCAL.DRIVES' });
  } else {
    const parentPath = currentPath.split('\\').slice(0, -1).join('\\');
    window.electron.sendMessageToMain({ commands: 'JRLC.LOCAL.LIST', data: { dirPath: parentPath } });
  }
}
const downloadProgress = ref({
  visible: false,
  percent: 0,
  fileName: ''
})
const uploadProgress = ref({
  visible: false,
  percent: 0,
  fileName: ''
})
const isDragOver = ref(false)
function handleDragStart(event: any, item: any) {
  if (!item.isDirectory) {
    event.dataTransfer.effectAllowed = 'copy'
    event.dataTransfer.setData('text/plain', JSON.stringify({
      fileName: item.name,
      host: ftpData.value.formData.host,
      port: ftpData.value.formData.port
    }))
    event.target.classList.add('dragging')
  } else {
    event.preventDefault()
  }
}
function handleDragEnd(event: any) {
  event.target.classList.remove('dragging')
}
function handleDragOver(event: any) {
  event.preventDefault()
  event.dataTransfer.dropEffect = 'copy'
  isDragOver.value = true
}
function handleDragLeave() {
  isDragOver.value = false
}
function handleDrop(event: any) {
  event.preventDefault()
  isDragOver.value = false
  const data = event.dataTransfer.getData('text/plain')
  if (!data) return
  try {
    const dragData = JSON.parse(data)
    if (!dragData.fileName || !dragData.host || !dragData.port) return
    downloadProgress.value.fileName = dragData.fileName
    downloadProgress.value.visible = true
    downloadProgress.value.percent = 0
    window.electron.sendMessageToMain({
      commands: 'JRLC.FTP.DOWNLOAD',
      data: {
        host: dragData.host,
        port: dragData.port,
        remoteFilePath: dragData.fileName,
        localDirPath: localFileData.value.pwd
      }
    })
    ElNotificationFn('success', '开始下载', `正在下载文件: ${dragData.fileName}`)
  } catch (error) {
    console.error('拖拽数据解析失败:', error)
  }
}
function handleLocalDragStart(event: any, item: any) {
  if (!item.isDirectory) {
    event.dataTransfer.effectAllowed = 'copy'
    event.dataTransfer.setData('text/plain', JSON.stringify({
      fileName: item.name,
      fullPath: item.fullPath,
      isLocalFile: true
    }))
    event.target.classList.add('dragging')
  } else {
    event.preventDefault()
  }
}
function handleLocalDragEnd(event: any) {
  event.target.classList.remove('dragging')
}
function handleTargetDrop(event: any) {
  event.preventDefault()
  isDragOver.value = false
  const data = event.dataTransfer.getData('text/plain')
  if (!data) return
  try {
    const dragData = JSON.parse(data)
    if (!dragData.isLocalFile || !dragData.fullPath) return
    uploadProgress.value.fileName = dragData.fileName
    uploadProgress.value.visible = true
    uploadProgress.value.percent = 0
    window.electron.sendMessageToMain({
      commands: 'JRLC.FTP.UPLOAD',
      data: {
        host: ftpData.value.formData.host,
        port: ftpData.value.formData.port,
        localFilePath: dragData.fullPath,
        remoteDirPath: targetFileData.value.pwd
      }
    })

    ElNotificationFn('success', '开始上传', `正在上传文件: ${dragData.fileName}`)
  } catch (error) {
    console.error('拖拽数据解析失败:', error)
  }
}
function addFtpListener(message: any) {
  const { cmd, data } = message
  switch (cmd) {
    case 'JRLC.FTP.CONNECT':
      window.electron.sendMessageToMain({ commands: 'JRLC.FTP.LIST', data: { host: ftpData.value.formData.host, port: ftpData.value.formData.port } })
      break;
    case 'JRLC.FTP.LIST':
      setFileList(data)
      break;
    case 'JRLC.LOCAL.DRIVES':
      setLocalDrives(data)
      break;
    case 'JRLC.LOCAL.LIST':
      setLocalFileList(data)
      break;
    case 'JRLC.FTP.ERROR':
      ElNotificationFn('error', '连接失败', message.data)
      break;
    case 'JRLC.FTP.DOWNLOAD_PROGRESS':
      downloadProgress.value.percent = data.percent
      break
    case 'JRLC.FTP.DOWNLOAD_SUCCESS':
      downloadProgress.value.visible = false
      ElNotificationFn('success', '下载成功', `文件 ${data.fileName} 已下载完成`)
      window.electron.sendMessageToMain({
        commands: 'JRLC.LOCAL.LIST',
        data: { dirPath: localFileData.value.pwd }
      })
      break
    case 'JRLC.FTP.UPLOAD_PROGRESS':
      uploadProgress.value.percent = data.percent
      break
    case 'JRLC.FTP.UPLOAD_SUCCESS':
      uploadProgress.value.visible = false
      ElNotificationFn('success', '上传成功', `文件 ${data.fileName} 已上传完成`)
      window.electron.sendMessageToMain({
        commands: 'JRLC.FTP.LIST',
        data: {
          host: ftpData.value.formData.host,
          port: ftpData.value.formData.port,
          path: targetFileData.value.pwd
        }
      })
      break
  }
}
onMounted(() => {
  window.electron.onMessageFromMain(addFtpListener)
  getLocalDrives()
})
onUnmounted(async () => {
  try {
    await window.electron.sendMessageToMain({
      commands: 'JRLC.FTP.CLOSE',
      data: {
        host: ftpData.value.formData.host,
        port: ftpData.value.formData.port
      }
    })
  } catch (error) {
    console.error('关闭FTP连接时出错:', error)
  }
})
</script>
<style lang="scss" scoped>
@import "@/styles/card.scss";
@import '@/styles/input.scss';

.xftp_container {
  padding: 20px;

  .fileSystem_container {
    height: calc(600px - 40px); // el-card的高度减去padding
    display: flex;
    gap: 20px;

    .file_item {
      &:hover {
        cursor: pointer;
        background: #125ea1
      }

      &.dragging {
        opacity: 0.5;
        background: #125ea1;
      }
    }

    .context-menu {
      position: fixed;
      background: #2b2b2b;
      border: 1px solid #444;
      border-radius: 4px;
      padding: 5px 0;
      z-index: 9999;
      min-width: 120px;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
      transform-origin: top left;
      user-select: none;

      .menu-list {
        list-style: none;
        margin: 0;
        padding: 0;

        li {
          padding: 8px 16px;
          cursor: pointer;

          white-space: nowrap;

          &:hover {
            background: #125ea1;
          }
        }
      }
    }

    .file-list-container {
      position: relative;
      height: calc(100% - 80px);
      overflow-y: auto;

      &::-webkit-scrollbar {
        width: 8px; // 滚动条整体宽度
        background-color: #424242; // 滚动条背景色
      }

      &::-webkit-scrollbar-thumb {
        background-color: #125ea1; // 滚动柱颜色
        border-radius: 4px; // 滚动柱圆角
        width: 6px; // 滚动柱宽度
      }

      &::-webkit-scrollbar-track {
        background-color: #424242; // 滚动条轨道颜色
        border-radius: 4px; // 轨道圆角
      }

      &.drag-over {
        background: rgba(18, 94, 161, 0.1);
        border: 2px dashed #125ea1;
      }
    }
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: all 0.2s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
  transform: scale(0.9);
}
</style>